﻿/* Author: Achim Schnell */

using System.Collections.Generic;
using AppFx.Tokenization;

namespace AppFx.Parsing
{
    /// <summary>
    /// Preparses tokens to add evaluation-info.
    /// </summary>
    public class PreParser
    {
        #region Constructors

        public PreParser() { }

        #endregion

        #region Methods

        /// <summary>
        /// Parses the specified tokens.
        /// </summary>
        /// <param name="inputTokens">The tokens.</param>
        /// <returns></returns>
        public IList<IParsedToken> Parse(IEnumerable<IToken> inputTokens)
        {
            List<IParsedToken> tokens = new List<IParsedToken>();
            foreach (var token in inputTokens)
            {
                switch (token.Type)
                {
                    case eTokenType.NumberLiteral:
                        tokens.Add(new ParsedToken(token, eParsedTokenType.Number));
                        break;
                    case eTokenType.Symbol:
                        tokens.Add(CreateTokenFromSymbol(token));
                        break;
                }
            }
            return tokens;
        }

        protected virtual IParsedToken CreateTokenFromSymbol(IToken token)
        {
            if (token.Content.Equals("("))
                return new ParsedToken(token, eParsedTokenType.L_Paren);
            else if (token.Content.Equals(")"))
                return new ParsedToken(token, eParsedTokenType.R_Paren);
            else
                return CreateOperatorToken(token);
        }

        protected virtual IParsedToken CreateOperatorToken(IToken token)
        {
            int precedence = 0;
            bool leftAssociative = false;

            switch (token.Content)
            {
                case "+":
                case "-":
                    leftAssociative = true;
                    precedence = 1;
                    break;
                case "*":
                case "/":
                    leftAssociative = true;
                    precedence = 2;
                    break;
                case "^":
                    precedence = 2;
                    break;
            }

            return new OperatorToken(token, eParsedTokenType.Operator, precedence, leftAssociative);
        }

        #endregion
    }
}
